package com.moon.cloud.common.utils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 集合工具类
 */
public class CollectionUtils {

    /**
     * 判断集合是否为空
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断集合是否不为空
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断 Map 是否为空
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * 判断 Map 是否不为空
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return !isEmpty(map);
    }

    /**
     * 判断数组是否为空
     */
    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 判断数组是否不为空
     */
    public static boolean isNotEmpty(Object[] array) {
        return !isEmpty(array);
    }

    /**
     * 获取集合第一个元素
     */
    public static <T> T first(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }
        return collection.iterator().next();
    }

    /**
     * 获取集合最后一个元素
     */
    public static <T> T last(List<T> list) {
        if (isEmpty(list)) {
            return null;
        }
        return list.getLast();
    }

    /**
     * 提取集合中指定字段的值（List<User> -> List<Long> userId）
     */
    public static <T, R> List<R> extract(Collection<T> collection, Function<T, R> mapper) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        return collection.stream().map(mapper).collect(Collectors.toList());
    }

    /**
     * 提取集合中指定字段的值（去重）
     */
    public static <T, R> List<R> extractDistinct(Collection<T> collection, Function<T, R> mapper) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        return collection.stream().map(mapper).distinct().collect(Collectors.toList());
    }

    /**
     * 集合转 Map（key 为指定字段）
     */
    public static <T, K> Map<K, T> toMap(Collection<T> collection, Function<T, K> keyMapper) {
        if (isEmpty(collection)) {
            return new HashMap<>();
        }
        return collection.stream().collect(Collectors.toMap(keyMapper, Function.identity(), (v1, v2) -> v1));
    }

    /**
     * 集合转 Map（指定 key 和 value）
     */
    public static <T, K, V> Map<K, V> toMap(Collection<T> collection, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        if (isEmpty(collection)) {
            return new HashMap<>();
        }
        return collection.stream().collect(Collectors.toMap(keyMapper, valueMapper, (v1, v2) -> v1));
    }

    /**
     * 集合分组
     */
    public static <T, K> Map<K, List<T>> groupBy(Collection<T> collection, Function<T, K> classifier) {
        if (isEmpty(collection)) {
            return new HashMap<>();
        }
        return collection.stream().collect(Collectors.groupingBy(classifier));
    }

    /**
     * 集合过滤
     */
    public static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        return collection.stream().filter(predicate).collect(Collectors.toList());
    }

    /**
     * 集合去重
     */
    public static <T> List<T> distinct(Collection<T> collection) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        return collection.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 集合去重（根据指定字段）
     */
    public static <T, R> List<T> distinctBy(Collection<T> collection, Function<T, R> keyExtractor) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        Set<R> seen = new HashSet<>();
        return collection.stream()
                .filter(item -> seen.add(keyExtractor.apply(item)))
                .collect(Collectors.toList());
    }

    /**
     * 集合分页
     */
    public static <T> List<T> page(List<T> list, int pageIndex, int pageSize) {
        if (isEmpty(list) || pageIndex < 1 || pageSize < 1) {
            return new ArrayList<>();
        }
        int fromIndex = (pageIndex - 1) * pageSize;
        if (fromIndex >= list.size()) {
            return new ArrayList<>();
        }
        int toIndex = Math.min(fromIndex + pageSize, list.size());
        return list.subList(fromIndex, toIndex);
    }

    /**
     * 集合分批处理
     */
    public static <T> List<List<T>> partition(List<T> list, int size) {
        if (isEmpty(list) || size < 1) {
            return new ArrayList<>();
        }
        List<List<T>> result = new ArrayList<>();
        for (int i = 0; i < list.size(); i += size) {
            result.add(list.subList(i, Math.min(i + size, list.size())));
        }
        return result;
    }

    /**
     * 两个集合的交集
     */
    public static <T> List<T> intersection(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c1) || isEmpty(c2)) {
            return new ArrayList<>();
        }
        return c1.stream().filter(c2::contains).distinct().collect(Collectors.toList());
    }

    /**
     * 两个集合的并集
     */
    public static <T> List<T> union(Collection<T> c1, Collection<T> c2) {
        List<T> result = new ArrayList<>();
        if (isNotEmpty(c1)) {
            result.addAll(c1);
        }
        if (isNotEmpty(c2)) {
            result.addAll(c2);
        }
        return result.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 两个集合的差集（c1 - c2）
     */
    public static <T> List<T> subtract(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c1)) {
            return new ArrayList<>();
        }
        if (isEmpty(c2)) {
            return new ArrayList<>(c1);
        }
        return c1.stream().filter(item -> !c2.contains(item)).collect(Collectors.toList());
    }

    /**
     * 判断集合是否包含任意元素
     */
    public static <T> boolean containsAny(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c1) || isEmpty(c2)) {
            return false;
        }
        return c1.stream().anyMatch(c2::contains);
    }

    /**
     * 判断集合是否包含所有元素
     */
    public static <T> boolean containsAll(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c2)) {
            return true;
        }
        if (isEmpty(c1)) {
            return false;
        }
        return c1.containsAll(c2);
    }

    /**
     * 安全的添加元素（避免 NPE）
     */
    public static <T> void addIfNotNull(Collection<T> collection, T element) {
        if (collection != null && element != null) {
            collection.add(element);
        }
    }

    /**
     * 安全的添加所有元素
     */
    public static <T> void addAllIfNotEmpty(Collection<T> target, Collection<T> source) {
        if (target != null && isNotEmpty(source)) {
            target.addAll(source);
        }
    }

    /**
     * 集合反转
     */
    public static <T> List<T> reverse(List<T> list) {
        if (isEmpty(list)) {
            return new ArrayList<>();
        }
        List<T> result = new ArrayList<>(list);
        Collections.reverse(result);
        return result;
    }

    /**
     * 集合随机打乱
     */
    public static <T> List<T> shuffle(List<T> list) {
        if (isEmpty(list)) {
            return new ArrayList<>();
        }
        List<T> result = new ArrayList<>(list);
        Collections.shuffle(result);
        return result;
    }

    /**
     * 集合求和
     */
    public static <T> Integer sumInt(Collection<T> collection, Function<T, Integer> mapper) {
        if (isEmpty(collection)) {
            return 0;
        }
        return collection.stream().map(mapper).reduce(0, Integer::sum);
    }

    /**
     * 集合求和（Long）
     */
    public static <T> Long sumLong(Collection<T> collection, Function<T, Long> mapper) {
        if (isEmpty(collection)) {
            return 0L;
        }
        return collection.stream().map(mapper).reduce(0L, Long::sum);
    }

    /**
     * 集合求平均值
     */
    public static <T> Double average(Collection<T> collection, Function<T, Number> mapper) {
        if (isEmpty(collection)) {
            return 0.0;
        }
        return collection.stream().mapToDouble(item -> mapper.apply(item).doubleValue()).average().orElse(0.0);
    }

    /**
     * 集合最大值
     */
    public static <T, R extends Comparable<R>> R max(Collection<T> collection, Function<T, R> mapper) {
        if (isEmpty(collection)) {
            return null;
        }
        return collection.stream().map(mapper).max(Comparable::compareTo).orElse(null);
    }

    /**
     * 集合最小值
     */
    public static <T, R extends Comparable<R>> R min(Collection<T> collection, Function<T, R> mapper) {
        if (isEmpty(collection)) {
            return null;
        }
        return collection.stream().map(mapper).min(Comparable::compareTo).orElse(null);
    }
}
